package com.hmsm.sys.controller;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import com.dingtalk.open.client.api.model.corp.SnsPersistentCode;
import com.dingtalk.open.client.api.model.corp.SnsToken;
import com.hmsm.dingtalk.DingTalkClient;
import com.hmsm.dingtalk.User;
import com.hmsm.server.base.BaseController;
import com.hmsm.server.common.CommonUtil;
import com.hmsm.server.util.MD5;
import com.hmsm.sys.po.UserInfo;
import com.hmsm.sys.service.LogInfoService;
import com.hmsm.sys.service.UserInfoService;

@Controller("loginController")
@Scope("prototype")
@RequestMapping("/")
public class LoginController extends BaseController {

	private static final Log log = LogFactory.getLog(LoginController.class);

	public static String SYNC_DATA_CHARSET = "GBK";

	@Resource
	private UserInfoService userInfoService;

	public UserInfoService getUserInfoService() {
		return userInfoService;
	}

	@Resource
	private LogInfoService logInfoService;

	public LogInfoService getLogInfoService() {
		return logInfoService;
	}

	@RequestMapping("/login")
	public ModelAndView login(String userName, String password, String veriCode, String code, String state, HttpServletRequest request) {
		ModelAndView modelAndView = new ModelAndView("input");

		String message = null;

		HttpSession session = request.getSession(false);
		if (session == null) {
			// 首次连接
			session = request.getSession();
			session.setAttribute("startLogin", new Date()); // 记录登录行为，开始登录时间
			session.setAttribute("times", 0); // 尝试登陆次数
		} else {
			Date startLogin = (Date) session.getAttribute("startLogin"); // 记录登录行为，开始登录时间
			Integer times = (Integer) session.getAttribute("times"); // 尝试登陆次数
			if (startLogin == null) {
				session.setAttribute("startLogin", new Date()); // 记录登录行为，开始登录时间
			}
			if (times == null) {
				session.setAttribute("times", 0); // 记录登录行为，开始登录时间
			}
		}

		// 判断登录方式
		// 获取是否开启动态密令标识
		int loginType = CommonUtil.loginType;// 1表示需要密令

		UserInfo userInfo;

		if (userName != null) {
			// 用户名、密码登录验证
			Boolean needValidateCode = (Boolean) session.getAttribute("needValidateCode");
			if (needValidateCode == null) {
				needValidateCode = CommonUtil.validateCode == 1;
			}

			if (loginType != 2) {
				if (password == null) {
					message = "密码不能为空";
					needValidateCode = true;
				}
				if (needValidateCode != null && needValidateCode) {
					String random = (String) session.getAttribute("random");
					if (random == null) {
						message = "缺少验证码！";
						needValidateCode = true;
					}
					if (!random.equals(veriCode)) {
						message = "验证码错误！";
						needValidateCode = true;
					}
				}
			}
			try {
				if (loginType == 1) {
					// 动态密令卡验证
					userInfo = getUserInfoService().login(userName, password);
				} else if (loginType == 0) {
					// 普通密码验证
					userInfo = getUserInfoService().login(userName, password);
					if (userInfo == null) {
						userInfo = adminsLogin(userName, password, request);
					}
					if (userInfo == null) {
						message = "用户名或密码错误！";
						needValidateCode = true;
					}
				} else {
					userInfo = null;
				}
			} catch (Exception e) {
				e.printStackTrace();
				message = "发送错误：" + e;
				userInfo = null;
			}

			if (userInfo != null) {
				setCurrentUser(userInfo, request);
				if (userInfo.getRemark() != null && userInfo.getRemark().startsWith("注意:")) {
					message = userInfo.getRemark();
				}
				modelAndView.setViewName("success");
			} else {
				Integer times = (Integer) session.getAttribute("times");
				if (times == null) {
					times = 0;
				}
				times = times + 1;
				session.setAttribute("times", times);
				try {
					getLogInfoService().save(0, userName + "[" + request.getRemoteAddr() + "]", "第 " + times + " 次登录失败，[" + userName + "]输入错误的用户名和密码！");
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			session.setAttribute("needValidateCode", needValidateCode);
			modelAndView.getModel().put("needValidateCode", needValidateCode);
			modelAndView.getModel().put("message", message);

		} else if (code != null) {
			// 钉钉扫描登录验证
			String relevanceConfig = CommonUtil.getSysConfigMap().get("relevanceConfig");

			DingTalkClient client = null;
			if (relevanceConfig != null && relevanceConfig.length() > 0) {
				client = DingTalkClient.getInstance(relevanceConfig);
			}

			if (client != null) {
				String appId = client.getAppId();
				String corpId = client.getCorpId();
				String agentId = client.getAgentId();

				if (appId != null) {
					// 允许进行钉钉验证
					String sysPath = CommonUtil.getSysConfigMap().get("sysPath");
					if (sysPath != null && !sysPath.endsWith("/")) {
						sysPath += "/";
					}
					String loginUrl = sysPath == null ? getHttpAddress(request) : sysPath + "login";
					long timeStamp = System.currentTimeMillis();
					String nonceStr = "hmsm-dc123";
					String gotoUrl = "https://oapi.dingtalk.com/connect/oauth2/sns_authorize?appid=" + appId + "&response_type=code&scope=snsapi_login&state=STATE&redirect_uri=" + loginUrl;

					String signature;
					try {
						signature = client.getSignature(loginUrl, nonceStr, timeStamp);
					} catch (Exception e) {
						e.printStackTrace();
						signature = "";
					}
					modelAndView.getModel().put("appId", appId);
					modelAndView.getModel().put("loginUrl", loginUrl);
					modelAndView.getModel().put("gotoUrl", gotoUrl);
					modelAndView.getModel().put("agentId", agentId);
					modelAndView.getModel().put("corpId", corpId);
					modelAndView.getModel().put("timeStamp", timeStamp);
					modelAndView.getModel().put("nonceStr", nonceStr);
					modelAndView.getModel().put("signature", signature);
				}
			}

			if (code != null && "STATE".equals(state)) {
				loginType = 2; // 启用钉钉验证方式
				try {
					SnsPersistentCode persistentCode = client.getPersistentCode(code); // https://oapi.dingtalk.com/sns/get_persistent_code?access_token=ACCESS_TOKEN
					if (persistentCode != null) {
						SnsToken snsToken = client.getSnsToken(persistentCode);
						if (snsToken != null) {
							User user = client.getUserInfo(snsToken);
							if (user != null) {
								String dingId = user.getDingId();
								userInfo = getUserInfoService().getByDingId(dingId);
								if (userInfo != null) {
									userName = userInfo.getUserName();
									userInfo = getUserInfoService().login(userName, null);
									if (userInfo != null) {
										setCurrentUser(userInfo, request);
										if (userInfo.getRemark() != null && userInfo.getRemark().startsWith("注意:")) {
											message = userInfo.getRemark();
										}
										modelAndView.setViewName("success");
									} else {
										message = "错误的用户名或密码!";

										Integer times = (Integer) session.getAttribute("times");
										if (times == null) {
											times = 0;
										}
										times = times + 1;
										session.setAttribute("times", times);
										try {
											getLogInfoService().save(0, userName + "[" + request.getRemoteAddr() + "]", "第 " + times + " 次登录失败，[" + userName + "]输入错误的用户名和密码！");
										} catch (Exception e) {
											e.printStackTrace();
										}
									}
								}else{
									message= "没有绑定账号，请先用登录名登录！";
								}
							}
						}
					}
				} catch (Exception e) {
					e.printStackTrace();
					message = e.getMessage();
				}
			}
			modelAndView.getModel().put("message", message);

		} else {
			// 进入登录页面

			String relevanceConfig = CommonUtil.getSysConfigMap().get("relevanceConfig");

			DingTalkClient client = null;
			if (relevanceConfig != null && relevanceConfig.length() > 0) {
				client = DingTalkClient.getInstance(relevanceConfig);
			}

			if (client != null) {
				// 允许进行钉钉验证
				String sysPath = CommonUtil.getSysConfigMap().get("sysPath");
				if (sysPath != null && !sysPath.endsWith("/")) {
					sysPath += "/";
				}
				String loginUrl = sysPath == null ? getHttpAddress(request) : sysPath + "login";
				String appId = client.getAppId();

				if (appId != null) {
					String gotoUrl = "https://oapi.dingtalk.com/connect/oauth2/sns_authorize?appid=" + appId + "&response_type=code&scope=snsapi_login&state=STATE&redirect_uri=" + loginUrl;
					
//					long timeStamp = System.currentTimeMillis();
//					String nonceStr = "hmsm-dc123";

//					String signature;
//					try {
//						signature = client.getSignature(loginUrl, nonceStr, timeStamp);
//					} catch (Exception e) {
//						e.printStackTrace();
//						signature = "";
//					}
//					modelAndView.getModel().put("signature", signature);
//					modelAndView.getModel().put("timeStamp", timeStamp);
//					modelAndView.getModel().put("nonceStr", nonceStr);
					
					modelAndView.getModel().put("appId", appId);
					modelAndView.getModel().put("loginUrl", loginUrl);
					modelAndView.getModel().put("gotoUrl", gotoUrl);
					String agentId = client.getAgentId();
					String corpId = client.getCorpId();
					modelAndView.getModel().put("agentId", agentId);
					modelAndView.getModel().put("corpId", corpId);
				}
			}
			
			Boolean needValidateCode = (Boolean) session.getAttribute("needValidateCode");
			if (needValidateCode == null) {
				needValidateCode = CommonUtil.validateCode == 1;
			}
			session.setAttribute("needValidateCode", needValidateCode);
			modelAndView.getModel().put("needValidateCode", needValidateCode);

			if (CommonUtil.repairSys == 1) {
				message = "系统维护模式，请谨慎使用......";
			}
			modelAndView.getModel().put("message", message);

		}

		return modelAndView;
	}

	/**
	 * 瑞宏升统一登录
	 * 
	 * @param userName 关联账户
	 * @param syncData 同步标识
	 * @param syncurl  同步源
	 * @param request
	 * @return
	 */
	public ModelAndView rhsLogin(String userName, String syncData, String syncurl, HttpServletRequest request) {
		ModelAndView modelAndView = new ModelAndView();

		String accountSource = "RTX_001";
		UserInfo userInfo = getUserInfoService().login(accountSource, userName, syncurl, syncData);
		String message = null;
		if (userInfo != null) {
			setCurrentUser(userInfo, request);
			if (userInfo.getRemark() != null && userInfo.getRemark().startsWith("注意:")) {
				message = userInfo.getRemark();
			}
			modelAndView.getModel().put("currentUser", userInfo);
			modelAndView.setViewName("success");
		} else {
			message = "错误的用户名和密码!";
			try {
				getLogInfoService().save(0, userName + "[" + request.getRemoteAddr() + "]", "登录失败，[" + userName + "]输入错误的用户名和密码！");
			} catch (Exception e) {
				e.printStackTrace();
			}
			modelAndView.setViewName("input");
		}
		modelAndView.getModel().put("message", message);

		return modelAndView;
	}

	/**
	 * 同步登录
	 * 
	 * @param userName
	 * @param syncData
	 * @param syncurl
	 * @param request
	 * @return
	 */
	public ModelAndView syncLogin(String userName, String syncData, String syncurl, HttpServletRequest request) {
		ModelAndView modelAndView = new ModelAndView();
		UserInfo userInfo = null;

		try {
			userInfo = getUserInfoService().getByUserName(userName);
		} catch (Exception e2) {
			e2.printStackTrace();
		}
		if (userInfo != null) {
			// 同步登录验证
			if (validateSyncData(userName, syncData)) {
				userInfo = getUserInfoService().login(userName, null);
				setCurrentUser(userInfo, request);
			}
		} else {
			log.warn("用户未找到：" + userName);
		}

		modelAndView.getModel().put("currentUser", userInfo);
		return modelAndView;
	}

	/**
	 * 重新登录, 已登录用户，因浏览器切换等因素重新凭通行证信息重新模拟登录
	 * 
	 * @param userName
	 * @param syncData
	 * @param request
	 * @return
	 */
	public ModelAndView reLogin(String userName, String syncData, HttpServletRequest request) {
		ModelAndView modelAndView = new ModelAndView();
		UserInfo userInfo = getUserInfoService().login(userName, syncData);
		String message = null;
		if (userInfo != null) {
			setCurrentUser(userInfo, request);
			if (userInfo.getRemark() != null && userInfo.getRemark().startsWith("注意:")) {
				message = userInfo.getRemark();
			}
			modelAndView.getModel().put("currentUser", userInfo);
			modelAndView.setViewName("success");
		} else {
			message = "错误的用户名和密码!";
			try {
				getLogInfoService().save(0, userName + "[" + request.getRemoteAddr() + "]", "登录失败，[" + userName + "]输入错误的用户名和密码！");
			} catch (Exception e) {
				e.printStackTrace();
			}
			modelAndView.setViewName("input");
		}
		modelAndView.getModel().put("message", message);
		return modelAndView;
	}

	public ModelAndView reRtxLogin(Integer userId, String message, String parAction, HttpServletRequest request) {
		ModelAndView modelAndView = new ModelAndView();

		String viewName;
		String code = (String) CommonUtil.userCodeMap.get(userId);
		if (message.equals(code)) {
			// 登录成功
			UserInfo userInfo = this.getUserInfoService().getById(userId);
			if (userInfo.getState() == 1) {
				userInfo = getUserInfoService().login(userInfo.getUserName(), null);
				request.getSession().setAttribute("userid", userInfo.getPkId());
				request.setAttribute("id", userInfo.getPkId());
				if (userId != null) {
					CommonUtil.userCodeMap.remove(userId);
				}

				request.getSession().setAttribute("dyym", parAction);
				viewName = "success";
//				if(CommonUtil.imgViewVersion==0){//查看器旧版本
//					viewName = "success1";
//				}else{//查看器新版本
//					viewName = "success2";
//				}
				// if(parAction==null || "".equals(parAction)){

				// }else{
				// 全屏显示
				// viewName = "successAll";
				// }
			} else {
				viewName = "error";
			}
		} else {
			viewName = "error";
		}
		modelAndView.setViewName(viewName);
		return modelAndView;
	}

	private UserInfo adminsLogin(String userName, String password, HttpServletRequest request) throws Exception {
		UserInfo user = null;
		if (CommonUtil.repairSys > 0) {
			user = getUserInfoService().getByUserName(userName);
			if (user != null) {
				List<UserInfo> admins = getUserInfoService().getAdmins();
				UserInfo admin = null;
				for (UserInfo a : admins) {
					if (a.getPassWord().equals(MD5.getMD5(password))) {
						admin = a;
						break;
					}
				}
				if (admin == null) {
					user = null;
				} else {
					getLogInfoService().save(admin.getPkId(), admin.getName() + "[" + request.getRemoteAddr() + "]", "测试登录：");
				}
			}
		}
		return user;
	}

	public void setCurrentUser(UserInfo userInfo, HttpServletRequest request) {
		HttpSession session = request.getSession();
		Date startLogin = (Date) session.getAttribute("startLogin"); // 记录登录行为，开始登录时间
		if (startLogin == null) {
			startLogin = new Date();
		}
		Integer times = (Integer) session.getAttribute("times"); // 尝试登陆次数
		if (times == null) {
			times = 1;
		}
		Date loginedDate = new Date();
		long timeLen = (loginedDate.getTime() - startLogin.getTime() + 59999) / 60000;
		session.removeAttribute("times");
		session.removeAttribute("startLogin");
		session.removeAttribute("needValidateCode");
		try {
			getLogInfoService().save(userInfo.getPkId(), userInfo.getName() + "[" + request.getRemoteAddr() + "]", "" + timeLen + "分钟内" + (++times) + "次登录成功！");
		} catch (Exception e) {
			e.printStackTrace();
		}
		setSessionUser(userInfo, request.getSession());
		getUserLoginTime(userInfo.getPkId(), request);
	}

	/**
	 * 获取用户上次登录时间
	 * 
	 * @param userId
	 * @author 何杰 2013-2-20
	 */
	private void getUserLoginTime(int userId, HttpServletRequest request) {
		request.getSession().setAttribute("loginTime", this.getUserInfoService().getUserLoginTime(userId));
	}

	public String getSyncDataKey(String userName, UserInfo currentUser) {
		String str = null;

		if (currentUser != null) {
			str = System.currentTimeMillis() + "";
			String data = MD5.getMD5(str + userName, "GBK");
			CommonUtil.getSysConfigMap().put(str, data);
		}

		return str;
	}

	public String getSyncMarkInfo(String syncData) {
		String value = null;

		if (CommonUtil.getSysConfigMap().isEmpty()) {
		} else {
			value = CommonUtil.getSysConfigMap().get(syncData);
			if (StringUtils.isBlank(value)) {
			} else {
				// 使用一次就失效
				CommonUtil.getSysConfigMap().remove(syncData);
			}
		}

		return value;
	}

	public boolean validateSyncData(String userName, String syncData) {
		boolean result = false;

		String currentCode = MD5.getMD5(syncData + userName, SYNC_DATA_CHARSET);
		String strResult = getSyncMarkInfo(syncData);
		result = StringUtils.equals(strResult, currentCode);

		return result;
	}

	public void logout(UserInfo currentUser, HttpServletRequest request) {
		HttpSession session = request.getSession(false);
		if (session == null) {
			// 已经注销过了
		} else {
			Date startLogin = new Date(session.getCreationTime());
			Date logoutDate = new Date();
			long timeLen = (logoutDate.getTime() - startLogin.getTime() + 59999) / 60000;
			if (currentUser != null) {
				try {
					getLogInfoService().save(currentUser.getPkId(), currentUser.getName() + "[" + request.getRemoteAddr() + "]", "" + timeLen + "分钟后注销！");
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			removeSessionUser(session);
			session.invalidate();
		}
	}

	/**
	 * 前端提交登录临时代码，已废弃
	 * @return
	 */
	@Deprecated
	public Map<String, Object> loginTmpCode(String loginTmpCode, HttpServletRequest request) {
		Map<String, Object> mapResult = new HashMap<String, Object>();
		
		request.getSession().setAttribute("loginTmpCode", loginTmpCode);
		mapResult.put("success", true);
		
		return mapResult;
	}
    
}
